package com.lixinlei.meetingfilm.showhystrix.command;

import com.netflix.hystrix.*;
import lombok.Data;

/**
 * HystrixCommand#run() 的调用是在隔离的线程（新线程）中完成的；
 */
public class CommandDemo extends HystrixCommand<String>{

    private String name;

    public CommandDemo(String name){
        super(Setter
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey("CommandHelloWorld"))
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.defaultSetter()
                                // 请求缓存开关
                                .withRequestCacheEnabled(false)
                                // 切换线程池隔离还是信号量隔离
//                                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
//                                .withExecutionIsolationSemaphoreMaxConcurrentRequests(5)
                                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                                // 熔断器
//                                .withCircuitBreakerForceOpen(true) // 强制开启熔断器
                                .withCircuitBreakerRequestVolumeThreshold(2) // 单位时间内的请求阈值
                                .withCircuitBreakerErrorThresholdPercentage(50) // 当满足请求阈值时，超过 50% 则开启熔断
                )
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("MyThreadPool"))
                .andThreadPoolPropertiesDefaults(
                    HystrixThreadPoolProperties.defaultSetter()
                        .withCoreSize(2)
                        .withMaximumSize(3).withAllowMaximumSizeToDivergeFromCoreSize(true)
                        .withMaxQueueSize(2)
                )
        );
        this.name = name;
    }

    /**
     * 降级
     * Command 实现降级很简单，覆盖 getFallback 方法即可；
     * getFallback() 和 run() 是一对一的， run() 方法出问题了，就会执行 getFallback() 方法；
     * 比如：run() 方法是影厅新增方法，如果执行失败了，getFallback() 方法就会返回客户端 0 个影片，让客户端再传个影片 id，可能就成功了；
     * getFallback() 方法中，一般都是定义自己的业务异常；
     * @return
     */
    @Override
    protected String getFallback() {
        String result = "Fallback[" + name + "]";
        System.err.println(result + " , currentThread-" + Thread.currentThread().getName());
        return result;
    }

    /**
     * CommandDemo 的 .execute() .queue() .observe() .toObservable() 的调用，最终都会调用到这个方法；
     * 业务方法就包装在这里面
     * @return
     * @throws Exception
     */
    @Override
    protected String run() throws Exception {
        String result = "CommandDemo[" + name + "]";

//        Thread.sleep(800l);

        if(name.startsWith("lixinlei")){
            int i = 6/0;
        }

        System.err.println(result + " , currentThread-" + Thread.currentThread().getName());

        return result;
    }

    /**
     * 如果 CommandDemo 的 name 是相同的，就认为是同一个请求，就可以用到请求缓存；
     * @return
     */
    @Override
    protected String getCacheKey() {
        return String.valueOf(name);
    }

}
